Segment Tree
ย - Last update: 2023-10-03

Bottom-Up SegTree

Point Update์™€ Range Query๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ SegTree์ด๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋Š” 2*N ๋งŒํผ ์„ ์–ธํ•˜๋ฉด ๋œ๋‹ค.

์ˆ˜์—ด์˜ Index๋Š” 0๋ถ€ํ„ฐ, ์ „์ฒด Tree์˜ Index๋Š” 1๋ถ€ํ„ฐ ์‚ฌ์šฉ๋˜๋Š” ์ƒ˜ํ”Œ ์ฝ”๋“œ์ด๋‹ค.

int N;
struct SegTree {
int d[2'000'010];
void build() {
for(int i = N - 1; i >= 1; --i) d[i] = d[i<<1] ^ d[i<<1|1];
}
void updatePoint(int p, int v) {
p += N;
d[p] = v;
for(p>>=1; p > 0; p>>=1) {
d[p] = d[p<<1] ^ d[p<<1|1];
}
}
int getRange(int l, int r) {
int ret = 0;
l += N, r += N;
for(;l<=r; l>>=1, r>>=1) {
if (l&1) ret ^= d[l++];
if (~r&1) ret ^= d[r--];
}
return ret;
}
} seg;

Top-Down SegTree

์ด ๊ฒฝ์šฐ๋Š” ๊ฐ€๊ธ‰์  ๋‹ค๋ฅธ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์ž. ์žฌ๊ท€ํ˜ธ์ถœ ์†๋„ ๋ฐ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์†ํ•ด๋ฅผ ๋ณธ๋‹ค.

Top-Down SegTree with Lazy

Lazy ์—ฐ์‚ฐ์€ Range Update ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค. ๋ง์…ˆ์˜ Range Update๋Š” ๊ฐ€๊ธ‰์  Fenwick์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ž. (Range Update๋ฅผ ๊ตฌ๊ฐ„ ๋์  2๊ฐœ์˜ Point Update๋กœ ๋Œ€์ฒดํ•œ ํ›„ ์ ๋ถ„ ๊ฐœ๋… ํ™œ์šฉํ•˜๋ฉด ๋œ๋‹ค)

๋ง์…ˆ์„ ์ œ์™ธํ•œ ๊ฒฝ์šฐ์—๋Š” SegTree ์‚ฌ์šฉ์ด ๊ฐ•์ œ๋˜๋Š”๋ฐ, Top-Down์ด Lazy ์ฒ˜๋ฆฌ์— ์••๋„์ ์œผ๋กœ ํŽธ๋ฆฌํ•˜๋‹ค. ์•„๋ž˜ ์˜ˆ์ œ๋Š” Lazy XOR ์—ฐ์‚ฐ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

int N;
struct SegNode {
int val;
int lazy;
};
struct LazySeg {
SegNode tree[2'000'010];
int arr[500'010];
int init(int x, int s, int e) {
if (s == e) return tree[x].val = arr[s];
int m = (s+e)>>1;
return tree[x].val = init(x<<1,s,m) ^ init(x<<1|1,m+1,e);
}
void init() {
init(1, 1, N);
}
void push(int x, int s, int e) {
if (tree[x].lazy == 0) return;
if ((e-s+1) % 2 != 0) tree[x].val ^= tree[x].lazy;
if (s != e) {
tree[x<<1].lazy ^= tree[x].lazy;
tree[x<<1|1].lazy ^= tree[x].lazy;
}
tree[x].lazy = 0;
}
void updateRange(int x, int s, int e, int l, int r, int v) {
push(x, s, e);
if (r < s || e < l) return;
if (l <= s && e <= r) {
tree[x].lazy ^= v;
push(x, s, e);
return;
}
int m = (s+e)>>1;
updateRange(x<<1,s,m,l,r,v);
updateRange(x<<1|1,m+1,e,l,r,v);
tree[x].val = tree[x<<1].val ^ tree[x<<1|1].val;
}
void updateRange(int l, int r, int v) {
updateRange(1, 1, N, l, r, v);
}
int getRange(int x, int s, int e, int l, int r) {
push(x, s, e);
if (r < s || e < l) return 0;
if (l <= s && e <= r) return tree[x].val;
int m = (s+e)>>1;
return getRange(x<<1,s,m,l,r) ^ getRange(x<<1|1,m+1,e,l,r);
}
int getRange(int l, int r) {
return getRange(1, 1, N, l, r);
}
} lazySeg;

Dynamic Top-Down SegTree with Lazy

์ดˆ๊ธฐ๊ฐ’์ด ์ฃผ์–ด์ง€์ง€ ์•Š๊ณ  ์ฟผ๋ฆฌ๋กœ๋งŒ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” Dynamicํ•˜๊ฒŒ ํ•„์š”ํ•œ ๊ตฌ๊ฐ„๋งŒ SegTree๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค. ๊ธฐ์กด x<<1, x<<1|1 ์ด ์ขŒ์šฐ ์ž์‹์œผ๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ๊ตฌ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ์ธ๋ฐ, ์ด๋ฅผ ์ง„์งœ tree ๊ตฌ์กฐ๋กœ ๋ฐ”๊พผ ๊ฒƒ.

int N;
struct SegNode {
int val;
int lazy;
SegNode* l;
SegNode* r;
} sn[4'000'000];
int sidx = 0;
SegNode* newNode() {
return &sn[sidx++];
}
struct LazySeg {
SegNode* root;
void init() {
root = newNode();
}
void push(SegNode* x, int s, int e) {
if (x == 0 || x->lazy == 0) return;
if ((e-s+1) % 2 != 0) x->val ^= x->lazy; // ๊ตฌ๊ฐ„ ํ™€์ˆ˜์ผ ๋•Œ๋งŒ xor ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค.
if (s != e) {
if (x->l == 0) x->l = newNode();
if (x->r == 0) x->r = newNode();
x->l->lazy ^= x->lazy;
x->r->lazy ^= x->lazy;
}
x->lazy = 0;
}
void updateRange(SegNode* x, int s, int e, int l, int r, int v) {
push(x, s, e);
if (x == 0) return;
if (r < s || e < l) return;
if (l <= s && e <= r) {
x->lazy ^= v;
push(x, s, e);
return;
}
int m = (s+e)>>1;
if (x->l == 0) x->l = newNode();
if (x->r == 0) x->r = newNode();
updateRange(x->l,s,m,l,r,v);
updateRange(x->r,m+1,e,l,r,v);
x->val = x->l->val ^ x->r->val;
}
void updateRange(int l, int r, int v) {
updateRange(root, 1, N, l, r, v);
}
int getRange(SegNode* x, int s, int e, int l, int r) {
push(x, s, e);
if (x == 0) return 0;
if (r < s || e < l) return 0;
if (l <= s && e <= r) return x->val;
int m = (s+e)>>1;
return getRange(x->l,s,m,l,r) ^ getRange(x->r,m+1,e,l,r);
}
int getRange(int l, int r) {
return getRange(root, 1, N, l, r);
}
} lazySeg;

Time Complexity

  • Point Update: O(logโกn)O(\log n)
  • Range Update: O(logโกn)O(\log n)
  • Range Query: O(logโกn)O(\log n)